from sqlalchemy.orm import Session
from sqlalchemy import func, or_
from typing import List, Optional
import math

from app.models.campsite import Campsite, CampsiteImage, CampsiteFollow
from app.schemas.campsite import CampsiteCreate, CampsiteUpdate, CampsiteImageCreate

def get_campsite(db: Session, campsite_id: int) -> Optional[Campsite]:
    """通过ID获取营地"""
    return db.query(Campsite).filter(
        Campsite.id == campsite_id,
        Campsite.is_deleted == False
    ).first()

def get_campsites(
    db: Session, 
    skip: int = 0, 
    limit: int = 100,
    search: Optional[str] = None,
    lat: Optional[float] = None,
    lon: Optional[float] = None,
    distance: Optional[float] = None
) -> List[Campsite]:
    """获取营地列表"""
    query = db.query(Campsite).filter(Campsite.is_deleted == False)
    
    # 如果有搜索条件
    if search:
        search_pattern = f"%{search}%"
        query = query.filter(
            or_(
                Campsite.name.like(search_pattern),
                Campsite.description.like(search_pattern),
                Campsite.address.like(search_pattern)
            )
        )
    
    # 如果有地理位置筛选
    if lat and lon and distance:
        # 这里简化处理，实际上应该使用地理空间查询
        # 这里使用近似计算，约6371公里作为地球半径
        earth_radius = 6371
        # 将距离转换为弧度
        distance_in_rad = distance / earth_radius
        
        # 纬度1度约等于111公里，使用近似计算，根据距离计算纬度范围
        lat_range = distance / 111
        # 经度1度的距离随纬度变化，在赤道处约等于111公里，两极为0
        lon_range = distance / (111 * math.cos(math.radians(lat)))
        
        query = query.filter(
            Campsite.latitude.between(lat - lat_range, lat + lat_range),
            Campsite.longitude.between(lon - lon_range, lon + lon_range)
        )
    
    # 统计每个营地的关注者数量和帖子数量
    query = query.order_by(Campsite.created_at.desc())
    
    campsites = query.offset(skip).limit(limit).all()
    
    # 填充关注者数量和帖子数量
    for campsite in campsites:
        campsite.follower_count = db.query(CampsiteFollow).filter(CampsiteFollow.campsite_id == campsite.id).count()
        campsite.post_count = len(campsite.posts)
    
    return campsites

def create_campsite(db: Session, campsite: CampsiteCreate) -> Campsite:
    """创建营地"""
    # 创建营地
    db_campsite = Campsite(
        name=campsite.name,
        description=campsite.description,
        address=campsite.address,
        latitude=campsite.latitude,
        longitude=campsite.longitude,
        cover_image=campsite.cover_image,
        phone=campsite.phone,
        website=campsite.website,
        business_hours=campsite.business_hours,
        price_range=campsite.price_range,
        facilities=campsite.facilities
    )
    db.add(db_campsite)
    db.commit()
    db.refresh(db_campsite)
    
    # 创建营地图片
    if campsite.images:
        for image_data in campsite.images:
            db_image = CampsiteImage(
                campsite_id=db_campsite.id,
                url=image_data.url,
                description=image_data.description,
                order=image_data.order
            )
            db.add(db_image)
        
        db.commit()
        db.refresh(db_campsite)
    
    return db_campsite

def update_campsite(db: Session, campsite_id: int, campsite: CampsiteUpdate) -> Optional[Campsite]:
    """更新营地信息"""
    db_campsite = get_campsite(db, campsite_id=campsite_id)
    if not db_campsite:
        return None
    
    # 更新营地数据
    update_data = campsite.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_campsite, key, value)
    
    db.commit()
    db.refresh(db_campsite)
    return db_campsite

def delete_campsite(db: Session, campsite_id: int) -> bool:
    """删除营地（软删除）"""
    db_campsite = get_campsite(db, campsite_id=campsite_id)
    if not db_campsite:
        return False
    
    db_campsite.is_deleted = True
    db.commit()
    return True

def add_campsite_image(db: Session, campsite_id: int, image: CampsiteImageCreate) -> Optional[CampsiteImage]:
    """添加营地图片"""
    db_campsite = get_campsite(db, campsite_id=campsite_id)
    if not db_campsite:
        return None
    
    db_image = CampsiteImage(
        campsite_id=campsite_id,
        url=image.url,
        description=image.description,
        order=image.order
    )
    
    db.add(db_image)
    db.commit()
    db.refresh(db_image)
    return db_image

def delete_campsite_image(db: Session, campsite_id: int, image_id: int) -> bool:
    """删除营地图片"""
    db_image = db.query(CampsiteImage).filter(
        CampsiteImage.id == image_id,
        CampsiteImage.campsite_id == campsite_id
    ).first()
    
    if not db_image:
        return False
    
    db.delete(db_image)
    db.commit()
    return True

def follow_campsite(db: Session, user_id: int, campsite_id: int) -> Optional[CampsiteFollow]:
    """关注营地"""
    # 检查是否已经关注
    existing_follow = db.query(CampsiteFollow).filter(
        CampsiteFollow.user_id == user_id,
        CampsiteFollow.campsite_id == campsite_id
    ).first()
    
    if existing_follow:
        return existing_follow
    
    # 创建关注关系
    db_follow = CampsiteFollow(user_id=user_id, campsite_id=campsite_id)
    db.add(db_follow)
    db.commit()
    db.refresh(db_follow)
    return db_follow

def unfollow_campsite(db: Session, user_id: int, campsite_id: int) -> bool:
    """取消关注营地"""
    db_follow = db.query(CampsiteFollow).filter(
        CampsiteFollow.user_id == user_id,
        CampsiteFollow.campsite_id == campsite_id
    ).first()
    
    if not db_follow:
        return False
    
    db.delete(db_follow)
    db.commit()
    return True

def get_campsite_followers(db: Session, campsite_id: int, skip: int = 0, limit: int = 100) -> List[CampsiteFollow]:
    """获取营地的关注者列表"""
    return db.query(CampsiteFollow).filter(
        CampsiteFollow.campsite_id == campsite_id
    ).offset(skip).limit(limit).all()

def get_user_followed_campsites(db: Session, user_id: int, skip: int = 0, limit: int = 100) -> List[Campsite]:
    """获取用户关注的营地列表"""
    campsites = db.query(Campsite).join(
        CampsiteFollow, CampsiteFollow.campsite_id == Campsite.id
    ).filter(
        CampsiteFollow.user_id == user_id,
        Campsite.is_deleted == False
    ).offset(skip).limit(limit).all()
    
    # 填充关注者数量和帖子数量
    for campsite in campsites:
        campsite.follower_count = db.query(CampsiteFollow).filter(CampsiteFollow.campsite_id == campsite.id).count()
        campsite.post_count = len(campsite.posts)
    
    return campsites 